package edu.hawaii.wattwaiter.wattdepotcommands;

import java.util.ArrayList;
import java.util.List;
import javax.xml.datatype.DatatypeConstants;
import javax.xml.datatype.XMLGregorianCalendar;
import org.wattdepot.client.BadXmlException;
import org.wattdepot.client.MiscClientException;
import org.wattdepot.client.NotAuthorizedException;
import org.wattdepot.client.ResourceNotFoundException;
import org.wattdepot.util.tstamp.Tstamp;

/**
 * Contacts a WattDepot server and collects the data for
 * carbon emitted for a given day.  It collects data for each hour of the
 * day and returns a List of the doubles obtained from the server.<br />
 * <br />
 * Collecting a <code>List</code> of doubles from the default server:
 * <pre>
 *  CarbonEmittedCollector clientConnection = new CarbonEmittedCollector(null);
 *  List&lt;Double&gt; rawList = clientConnection.getList( "2009-11-01" );
 * </pre>
 * 
 * @author David Mau
 */
public class CarbonEmittedCollector extends WattDepotClientCommand {
  // A variable to hold the interval that the command will use.
  private static int interval = 60;
  // A variable to hold this class' name
  private static String name = "CarbonEmittedCollector: ";
  // A variable to help check how long the date String should be.
  private static String dateFormat = "YYYY-MM-DD";
  // A variable for when the collector should start collecting data.
  private static int oneWeekBefore = -7;

  /**
   * Readies the client for connecting to a WattDepot server.
   * 
   * @see WattDepotClientCommand
   * @param anotherServer An optional argument that can be given to attempt to
   * connect to a different WattDepot server than the default.
   */
  public CarbonEmittedCollector( String anotherServer ) {
    // Call the super class to set things up.
    super( anotherServer );
  }
  
  /**
   * Collects the carbon emitted data from a WattDepot server for
   * the specified day.
   * 
   * @param date The given date to collect data for.  Form of the date should be
   * in YYYY-MM-DD, where Y is for years, M is for months, and D is for days.
   * @return A List with the data collected from the server.
   */
  public List<Double> getList ( String date ) {
    // Create the ArrayList to contain the output.
    ArrayList<Double> output = new ArrayList<Double>();
    
    // If the date provided is a null String,
    if ( date == null ) {
      // If in debug mode, print out that the connection was bad.
      if ( consoleDebugMode ) {
        System.out.println( name + nullDate );
      }
      // Return the list of all zeros.
      return allZeroList;
    }
    
    // Stop right away if we cannot contact server.
    if (!client.isHealthy()) {
      // If in debug mode, print out that the connection was bad.
      if ( consoleDebugMode ) {
        System.out.println( name + serverConnectionError + 
            client.getWattDepotUri() );
      }
      // Return the list of all zeros.
      return allZeroList;
    }
    
    // If the date given is not the proper length,
    if ( date.length() != dateFormat.length() ) {
      // If in debug mode, print out that the given date was bad.
      if ( consoleDebugMode ) {
        System.out.println( name + badDate + date );
      }
      // Return the list of all zeros.
      return allZeroList;
    }
    
    // Convert the date String into two XML ones.
    // First, the start time.
    XMLGregorianCalendar xmlTimeStart = null;
    try {
      xmlTimeStart = Tstamp.makeTimestamp( date );
    }
    catch (Exception e) {
      // If in debug mode, print out that the given date was bad.
      if ( consoleDebugMode ) {
        System.out.println( name + badDate + date );
      }
      // Return the list of all zeros.
      return allZeroList;
    }
    
    // Go back a week.
    xmlTimeStart = Tstamp.incrementDays( xmlTimeStart, oneWeekBefore);
    // Create a time for the analysis to end.
    XMLGregorianCalendar xmlTimeEnd = xmlTimeStart;
    xmlTimeEnd = Tstamp.incrementDays( xmlTimeEnd, 1);
    
    // Until the end of the time duration,
    while ( xmlTimeStart.compare(xmlTimeEnd) == DatatypeConstants.LESSER ) {
      double tempCarbon;
      
      // Collect data for the hour from the server.
      try {
        tempCarbon = client.getCarbonEmitted( oahuGrid, xmlTimeStart, 
            Tstamp.incrementHours( xmlTimeStart, 1), interval );
      }
      catch (NotAuthorizedException exception) {
        // If in debug mode, print out that the client was not authorized to view this information.
        if ( consoleDebugMode ) {
          System.out.println( name + notAuthorized + exception );
        }
        // Return the list of all zeros.
        return allZeroList;
      }
      catch (ResourceNotFoundException exception) {
        // If in debug mode, print out that the resource was not found.
        if ( consoleDebugMode ) {
          System.out.println( name + notAuthorized + exception );
        }
        // Return the list of all zeros.
        return allZeroList;
      }
      catch (BadXmlException exception) {
        // If in debug mode, print out that the server returned bad xml.
        if ( consoleDebugMode ) {
          System.out.println( name + badXml + exception );
        }
        // Return the list of all zeros.
        return allZeroList;
      }
      catch (MiscClientException exception) {
        // If in debug mode, print out that the client encountered an unknown error.
        if ( consoleDebugMode ) {
          System.out.println( name + miscClient + exception );
        }
        // Return the list of all zeros.
        return allZeroList;
      }
      
      // Add the information given by the client into the list.
      output.add( tempCarbon );
      
      // Increment the start time by one hour.
      xmlTimeStart = Tstamp.incrementHours( xmlTimeStart, 1 );
    }
    
    // Return the output once it is finished.
    return output;
  }
}
